1 00:00:00,430 --> 00:00:04,690 Alrighty, in this lecture, we're going to be scripting the service that will set up and handle all 2 00:00:04,690 --> 00:00:07,060 of the lockers in our game. 3 00:00:07,060 --> 00:00:12,490 These lockers are going to act as safe spaces that players can hide inside of, to avoid being attacked 4 00:00:12,490 --> 00:00:14,260 by our Squidward AI. 5 00:00:14,290 --> 00:00:19,480 The plan is, is that a player will interact with a prompt on the outside of the door, and will tween 6 00:00:19,480 --> 00:00:24,400 their character to move inside of the locker, and at that point, they will only be able to see out 7 00:00:24,400 --> 00:00:27,340 of these grills when they're inside of the locker. 8 00:00:27,340 --> 00:00:31,060 And then there will be a prompt inside that they can use to exit the locker. 9 00:00:31,060 --> 00:00:37,240 Now we have a lot of these lockers in our map, specifically in the Krusty Krab basement and then lockers 10 00:00:37,240 --> 00:00:37,780 folder. 11 00:00:37,780 --> 00:00:42,070 We have a whole bunch that we've placed throughout the basement, and we need to go ahead and set up 12 00:00:42,070 --> 00:00:43,960 the functionality for each one of these lockers. 13 00:00:43,960 --> 00:00:46,360 So we're going to use our locker service to do that. 14 00:00:46,360 --> 00:00:49,810 And this is also going to act as a class for all of our lockers. 15 00:00:50,050 --> 00:00:53,020 So inside of here we're going to need a few services. 16 00:00:53,020 --> 00:00:55,030 One is going to be the player service. 17 00:00:56,040 --> 00:00:59,430 We're going to need the server script service. 18 00:01:03,540 --> 00:01:05,610 We will need replicated storage. 19 00:01:08,600 --> 00:01:11,240 We're going to need server storage. 20 00:01:13,900 --> 00:01:16,750 And then we're also going to need the sound service. 21 00:01:20,480 --> 00:01:23,300 Now we can create the variable that will represent this module script. 22 00:01:23,300 --> 00:01:25,850 We'll call it locker service. 23 00:01:25,970 --> 00:01:29,150 And we'll make sure to return that at the end of our script. 24 00:01:30,200 --> 00:01:35,330 And then we're also going to need to create the table that will act as the meta table for all of our 25 00:01:35,330 --> 00:01:36,320 locker objects. 26 00:01:36,320 --> 00:01:39,560 So locker service meta table. 27 00:01:39,560 --> 00:01:45,860 And then inside of that we're going to set the underscore underscore index meta method equal to itself. 28 00:01:45,860 --> 00:01:48,980 And now we can go ahead and start referencing a bunch of different events. 29 00:01:48,980 --> 00:01:52,220 But first let's go ahead and grab our better tween module script. 30 00:01:52,220 --> 00:01:58,850 So we can require that from server script service dot server dot modules dot better tween. 31 00:01:59,120 --> 00:02:02,060 We're going to want to get the game comms event. 32 00:02:02,060 --> 00:02:05,960 So that's in replicated storage dot events dot remotes dot game communication. 33 00:02:05,960 --> 00:02:09,020 And we're going to get the game comms enum along with that. 34 00:02:09,020 --> 00:02:14,690 So require replicated storage dot modules dot enums dot game communication. 35 00:02:15,110 --> 00:02:17,960 We're going to get the camera manipulation event. 36 00:02:17,960 --> 00:02:22,040 So in replicated storage the events dot remotes dot manipulate camera. 37 00:02:22,040 --> 00:02:26,720 And then we can get the camera manipulation enum for this as well. 38 00:02:26,720 --> 00:02:34,460 So we'll require for replicated storage dot modules dot enums dot camera manipulation enum. 39 00:02:35,470 --> 00:02:38,080 We're also going to get the update guy event. 40 00:02:38,080 --> 00:02:42,700 So replicated storage, dot events, dot remotes, dot update UI, and then the enum for this as well. 41 00:02:42,700 --> 00:02:50,380 Guy actions enum require for replicated storage, dot modules, dot enums dot guy actions enum. 42 00:02:50,740 --> 00:02:55,240 We're also going to reference two sounds inside of replicated storage, one sound we can call Lock or 43 00:02:55,240 --> 00:02:58,690 Open Sound, and we'll play this to go ahead and open the locker. 44 00:02:58,690 --> 00:03:00,610 So that's in our instances folder. 45 00:03:00,610 --> 00:03:02,500 Dot sounds dot locker open. 46 00:03:02,500 --> 00:03:05,830 And then we can get our locker close sound. 47 00:03:05,980 --> 00:03:09,970 So replicated storage dot instances dot sounds dot locker close. 48 00:03:11,610 --> 00:03:16,920 And then we're going to have a table to act as a cache to store all of the current lockers in the game. 49 00:03:17,980 --> 00:03:24,280 And then we're going to define a constant that will represent how long we want to tween the door opening 50 00:03:24,280 --> 00:03:25,090 and closing for. 51 00:03:25,090 --> 00:03:28,480 So we'll call it door move duration. 52 00:03:28,480 --> 00:03:30,580 And we'll set it to something like 0.6 seconds. 53 00:03:30,580 --> 00:03:31,900 I found that to be pretty good. 54 00:03:32,690 --> 00:03:35,660 And then from this point, we're going to need quite a few private functions. 55 00:03:35,660 --> 00:03:41,510 One function we can create is to play a sound, and we'll use the game comms event to play the sound 56 00:03:41,510 --> 00:03:42,140 to players. 57 00:03:42,140 --> 00:03:44,030 But I wanted to create a private function. 58 00:03:44,030 --> 00:03:48,530 That way we only need to type out the function itself without having to, you know, use the game comms 59 00:03:48,530 --> 00:03:51,020 event and fire to all the clients and fill all that stuff out. 60 00:03:51,020 --> 00:03:52,340 It can get a little bit long. 61 00:03:52,340 --> 00:03:56,630 So we could pass to this function a sound instance, which is a sound. 62 00:03:56,630 --> 00:04:02,900 We can pass the parent for the part, which is a bass part, and we'll get the position from this parent 63 00:04:02,900 --> 00:04:04,730 and set that for the sound. 64 00:04:05,060 --> 00:04:10,670 We're going to need a function to open and then close a door on our locker. 65 00:04:10,670 --> 00:04:15,740 And the reason we need to do this is for example, the player wants to enter or leave the locker, the 66 00:04:15,740 --> 00:04:18,470 door is going to open, and then the door is going to close, right. 67 00:04:18,470 --> 00:04:20,390 So we'll have that as well. 68 00:04:20,570 --> 00:04:24,710 And then we'll have a local function to listen for when a prompt gets triggered. 69 00:04:24,710 --> 00:04:27,500 So we'll call on prompt triggered. 70 00:04:27,500 --> 00:04:32,600 And this will listen to when different you know prompts inside of our lockers get triggered afterwards 71 00:04:32,600 --> 00:04:37,520 we can go ahead and create the function that will act as the constructor for our locker service. 72 00:04:37,520 --> 00:04:41,300 So function locker service dot new. 73 00:04:41,330 --> 00:04:43,550 We'll pass a model for the locker. 74 00:04:46,490 --> 00:04:53,090 We're also going to need a function inside of the locker service meta table for the objects themselves. 75 00:04:53,090 --> 00:04:57,530 So on specific lockers, we want to have the ability to set the occupant. 76 00:04:57,770 --> 00:04:59,960 And we'll pass a character model to this. 77 00:05:00,710 --> 00:05:03,470 We want to have the ability to remove an occupant. 78 00:05:03,470 --> 00:05:06,830 So locker service metatable remove occupant. 79 00:05:07,820 --> 00:05:13,220 We want to have the ability to enable and disable the prompts so we can have a function locker service 80 00:05:13,220 --> 00:05:15,770 meta table enable prompt. 81 00:05:16,840 --> 00:05:22,750 And then we can also do function locker service meta table disable prompt. 82 00:05:24,070 --> 00:05:28,360 And the only function we're going to need for our service itself is a start function. 83 00:05:28,360 --> 00:05:31,690 So function locker service start. 84 00:05:31,690 --> 00:05:36,850 And this is where we'll loop through every single locker model that is inside of the workspace. 85 00:05:37,000 --> 00:05:39,760 Krusty Krab basement lockers. 86 00:05:39,760 --> 00:05:46,840 We'll get all of the children in there, and we'll use our constructor and locker service dot new and 87 00:05:46,840 --> 00:05:48,490 pass the locker model. 88 00:05:49,100 --> 00:05:51,170 So let's go ahead and fill out our constructor. 89 00:05:51,500 --> 00:05:53,360 Inside of here we can define a table. 90 00:05:53,360 --> 00:05:54,560 We'll call it self. 91 00:05:55,100 --> 00:06:00,320 And then inside of this table, we'll have a property to refer to the locker model itself, which is 92 00:06:00,320 --> 00:06:03,770 equal to the locker model self dot occupant. 93 00:06:03,770 --> 00:06:05,390 We're going to set to nil for now. 94 00:06:05,510 --> 00:06:11,840 We're going to have a reference to the enter prompt which is equal to the locker model dot body dot 95 00:06:11,840 --> 00:06:14,540 attachment dot proximity prompt. 96 00:06:14,540 --> 00:06:19,340 So inside of the body there's an attachment for the entering. 97 00:06:19,340 --> 00:06:23,510 And then we also have an attachment for the exit prompt when a player is inside of it. 98 00:06:23,510 --> 00:06:24,950 So that's the locker model. 99 00:06:24,950 --> 00:06:26,030 Get the body. 100 00:06:26,180 --> 00:06:27,830 There's another attachment in there. 101 00:06:27,830 --> 00:06:29,690 And that's called attachment exit. 102 00:06:29,690 --> 00:06:32,900 And we'll get the proximity prompt in that as well. 103 00:06:32,900 --> 00:06:37,880 And then from this point we can go ahead and set the metta table on our locker. 104 00:06:37,880 --> 00:06:40,460 So locker service metta table. 105 00:06:40,760 --> 00:06:45,770 And then we also want to listen for when our enter prompt is triggered. 106 00:06:46,340 --> 00:06:49,250 So we will connect a function to this. 107 00:06:49,250 --> 00:06:50,900 And that gets passed a player. 108 00:06:50,900 --> 00:06:54,710 And we can also go ahead and denote these as proximity prompts. 109 00:06:57,930 --> 00:07:00,600 So we'll listen for when it gets triggered. 110 00:07:00,600 --> 00:07:02,850 And then we can call our on prompt triggered function. 111 00:07:02,850 --> 00:07:05,940 And we could pass the object itself and the player that triggered it. 112 00:07:05,940 --> 00:07:11,580 And then we do the exact same thing for the exit prompt that triggered we'll connect a function, get 113 00:07:11,580 --> 00:07:14,820 the player, and then call our on prompt triggered function. 114 00:07:14,820 --> 00:07:17,040 And we'll pass self and the player. 115 00:07:17,040 --> 00:07:21,810 After that, we can go ahead and insert our object into our current lockers table. 116 00:07:21,810 --> 00:07:22,860 So we'll pass self here. 117 00:07:22,860 --> 00:07:25,500 And then we'll return self at the end in case we need to. 118 00:07:26,010 --> 00:07:30,060 So let's go ahead and I guess fill out our on prompt triggered function. 119 00:07:30,060 --> 00:07:33,630 What do we want to do when a prompt inside of our locker gets triggered. 120 00:07:33,630 --> 00:07:38,610 Well first we want to get the self or the object and then the player. 121 00:07:39,450 --> 00:07:42,600 And we want to ensure that this player has a character model. 122 00:07:42,600 --> 00:07:47,010 So if this player does not have a character model then we're just going to return. 123 00:07:47,490 --> 00:07:52,830 The next thing we need to check is whether or not the player is already in occupant of this locker. 124 00:07:52,830 --> 00:07:58,080 If that's the case, then when the prompt gets triggered, we want to go ahead and remove the player 125 00:07:58,080 --> 00:07:59,070 out of the locker. 126 00:07:59,070 --> 00:08:06,870 So if the player character is equal to the self dot occupant, then we can call our open and close door 127 00:08:06,870 --> 00:08:07,680 function. 128 00:08:07,680 --> 00:08:13,110 And then we can also remove the occupant from inside our locker. 129 00:08:14,140 --> 00:08:21,490 Otherwise, if there is no occupant inside of the locker, then what we could do is we first want to 130 00:08:21,490 --> 00:08:25,150 ensure that the player is not already inside of, let's say, a different locker. 131 00:08:25,150 --> 00:08:29,410 So let's say there are two lockers right next to each other, and the player is able to see the prompt 132 00:08:29,410 --> 00:08:32,620 on the other one, and they try to activate that to move into the other locker. 133 00:08:32,620 --> 00:08:34,270 Well, we're going to have problems. 134 00:08:34,270 --> 00:08:38,470 So when we put a player inside of a locker we're going to set an attribute on that player. 135 00:08:38,470 --> 00:08:42,010 We could call it something like inside locker and set that to either true or false. 136 00:08:42,010 --> 00:08:44,470 That way we can keep track of the players in a locker. 137 00:08:44,470 --> 00:08:48,340 And that way also our AI can tell whether or not a player is in a locker. 138 00:08:48,340 --> 00:08:54,130 So we can have an if statement to check if this player and get an attribute like inside Locker. 139 00:08:54,130 --> 00:08:59,050 So if they're already inside of a locker, then we're going to use our update guy event and fire to 140 00:08:59,050 --> 00:09:05,560 this particular player here and give them a GUI actions enum small message, and we can give them some 141 00:09:05,560 --> 00:09:08,950 text like you are already in a locker. 142 00:09:10,220 --> 00:09:14,180 Otherwise, if there is an occupant in there and that player is not the occupant. 143 00:09:14,180 --> 00:09:16,790 So if self dot occupant is truthy. 144 00:09:17,370 --> 00:09:23,100 Then we need to use the update event and fire again to this particular player that this locker is currently 145 00:09:23,100 --> 00:09:23,760 occupied. 146 00:09:23,760 --> 00:09:29,520 So GUI actions enum dot small message and we give them some text like. 147 00:09:30,350 --> 00:09:33,350 This locker is occupied. 148 00:09:33,410 --> 00:09:37,700 The next thing we can go ahead and do is work on our open close door function. 149 00:09:37,970 --> 00:09:44,000 So when we want to open and close the door, first off, we want to disable the prompt inside of our 150 00:09:44,000 --> 00:09:44,420 locker. 151 00:09:44,420 --> 00:09:47,990 So we could use that self disable prompt function. 152 00:09:47,990 --> 00:09:53,030 And that means we're going to have to pass the self or the object to this, uh function here. 153 00:09:53,030 --> 00:09:54,800 So we can go ahead and pass self right here. 154 00:09:54,800 --> 00:09:59,300 And then the disable and enable prompt functions are actually pretty easy to do. 155 00:09:59,300 --> 00:10:05,630 So we can just go down here when we want to enable the prompt we'll do self dot enter prompt dot enabled. 156 00:10:05,630 --> 00:10:06,950 We'll set that to true. 157 00:10:06,950 --> 00:10:12,890 Otherwise we can just set self dot enter prompt dot enabled equal to false when we want to disable it. 158 00:10:13,370 --> 00:10:16,010 So we go ahead and disable that external prompt. 159 00:10:16,280 --> 00:10:21,320 And then what we're going to do is we're going to set the door of the locker kankali to false. 160 00:10:21,320 --> 00:10:23,660 So self dot locker model. 161 00:10:24,410 --> 00:10:28,940 Dot door we're going to set can collide equal to false. 162 00:10:28,940 --> 00:10:31,820 That way nobody collides with the door when it opens. 163 00:10:32,380 --> 00:10:36,580 And then what we're going to do is we're going to get a tween info for how long we want to open the 164 00:10:36,580 --> 00:10:36,790 door. 165 00:10:36,790 --> 00:10:39,010 So we're going to do tween info dot new. 166 00:10:39,760 --> 00:10:44,560 We're going to set the time as our door move duration, and then again, we can be a little fancy and 167 00:10:44,560 --> 00:10:46,960 do an enemy's style like sign. 168 00:10:47,570 --> 00:10:53,300 And then we're also going to ensure to store the original key frame of the lockers hinge. 169 00:10:53,300 --> 00:10:55,520 So hinge dot key frame. 170 00:10:55,520 --> 00:11:02,300 And then we're going to use the better tween service and tween our self dot locker dot hinge. 171 00:11:02,420 --> 00:11:06,650 So inside of our locker model here we have the door. 172 00:11:06,650 --> 00:11:08,540 And there's a hinge that the door is attached to. 173 00:11:08,540 --> 00:11:13,580 And we rotate this hinge to you know go ahead and rotate the door outwards. 174 00:11:14,000 --> 00:11:18,590 So for example if I did 90 degrees we'll open the door like that. 175 00:11:18,590 --> 00:11:20,240 I think we want to swing it out a little bit more. 176 00:11:20,240 --> 00:11:21,050 But. 177 00:11:22,190 --> 00:11:23,870 We'll do something in a little bit here. 178 00:11:23,870 --> 00:11:28,670 So we swing open the hinge, we open the door, make sure can collide is off on it. 179 00:11:29,180 --> 00:11:31,280 So we pass self that locker hinge. 180 00:11:31,280 --> 00:11:33,680 We pass the tween info we just created. 181 00:11:33,890 --> 00:11:37,820 And then the goal is going to change the see frame of our hinge. 182 00:11:37,820 --> 00:11:43,580 And that's going to be equal to the self dot locker dot hinge and the see frame. 183 00:11:43,580 --> 00:11:52,220 What we can do is we can multiply this and we can do a see frame dot angles zero on the x axis. 184 00:11:52,220 --> 00:11:54,200 And then we want to rotate it on the y axis. 185 00:11:54,200 --> 00:11:58,370 So math dot rad we could do a little bit more than 90 degrees. 186 00:11:58,370 --> 00:11:59,960 We could do like 105 degrees. 187 00:11:59,960 --> 00:12:00,950 That might be good. 188 00:12:00,950 --> 00:12:03,320 And then zero on the z axis. 189 00:12:03,320 --> 00:12:08,660 And then after that we can use our play sound function and play like our locker open sound. 190 00:12:09,650 --> 00:12:13,610 And the parent for that would be the self dot locker dot body. 191 00:12:14,120 --> 00:12:17,120 So let's go ahead and fill out this function real quick as well. 192 00:12:17,150 --> 00:12:21,770 All we're going to do in here is refer to our game comms event and fire to all the clients to play a 193 00:12:21,770 --> 00:12:22,100 sound. 194 00:12:22,100 --> 00:12:26,270 So game comms enum dot two client dot play sound. 195 00:12:26,660 --> 00:12:31,490 The sound is going to be equal to the sound instance passed to the function play at point. 196 00:12:31,490 --> 00:12:37,070 We're going to set that to true and the position is going to be equal to the parent dot position that 197 00:12:37,070 --> 00:12:38,360 is passed to the function. 198 00:12:38,360 --> 00:12:42,890 After that we can go ahead and yield for the door move duration. 199 00:12:42,890 --> 00:12:47,480 And then after that is done, we need to go ahead and then close the door. 200 00:12:47,480 --> 00:12:52,760 So better tween tween self dot locker dot hinge. 201 00:12:53,420 --> 00:12:55,070 We'll do the same tween info here. 202 00:12:55,070 --> 00:13:01,880 But instead we want to set the key frame of our hinge back to the original key frame. 203 00:13:01,880 --> 00:13:03,530 And then again we can play a sound. 204 00:13:03,530 --> 00:13:09,740 And this time we're going to play the locker closed sound and then pass self dot locker dot body. 205 00:13:10,040 --> 00:13:14,120 After this point we can go ahead and set can collide back on our door to true. 206 00:13:14,120 --> 00:13:19,490 So self dot locker dot door dot can collide is equal to true. 207 00:13:19,490 --> 00:13:20,570 And oops. 208 00:13:20,570 --> 00:13:23,180 Let me rename this to locker model. 209 00:13:23,180 --> 00:13:24,950 Actually let me copy this. 210 00:13:24,950 --> 00:13:27,140 Make sure we stay consistent here. 211 00:13:27,140 --> 00:13:31,760 So this is the locker model not just the locker. 212 00:13:33,910 --> 00:13:34,930 Okay, good. 213 00:13:34,930 --> 00:13:38,800 And then again we're going to yield for that door move duration. 214 00:13:39,100 --> 00:13:47,350 And finally, if we do not have an occupant we're going to make sure if not occupant, then we're going 215 00:13:47,350 --> 00:13:52,360 to go ahead and enable the prompt inside of our object. 216 00:13:52,570 --> 00:13:57,580 Now since this function is going to be yielding and we want to remove the occupant at the same time 217 00:13:57,580 --> 00:14:02,890 that we're opening and closing the door, we should spawn this function in a new thread. 218 00:14:04,090 --> 00:14:06,520 And then we can pass self to that function. 219 00:14:06,520 --> 00:14:10,750 And that allows us to immediately call our self remove occupant function. 220 00:14:10,750 --> 00:14:12,490 So let's go ahead and fill this one out. 221 00:14:12,730 --> 00:14:20,380 So to go ahead and remove an occupant first we need to check if there isn't an occupant already inside 222 00:14:20,380 --> 00:14:20,560 of it. 223 00:14:20,560 --> 00:14:25,150 So if there is no occupant then we don't need to do anything. 224 00:14:25,660 --> 00:14:31,720 Otherwise we're going to set the self dot exit prompt dot enabled equal to false. 225 00:14:32,460 --> 00:14:34,770 And then we're going to get the player. 226 00:14:35,100 --> 00:14:37,830 Players get player from character. 227 00:14:37,830 --> 00:14:40,050 I'm going to pass self to occupant. 228 00:14:40,500 --> 00:14:46,320 And then we're going to use the game comms event and fire to this particular player here. 229 00:14:46,770 --> 00:14:49,950 And we can give them the game comms enum. 230 00:14:50,860 --> 00:14:57,100 And we want them to stop a sound, because when we add or set an occupant inside of our locker, we're 231 00:14:57,100 --> 00:14:59,860 going to be playing a breathing sound. 232 00:14:59,860 --> 00:15:05,740 And when they exit or are removed from the locker, we need to stop playing that sound. 233 00:15:05,740 --> 00:15:09,340 So we're going to tell them to stop a sound. 234 00:15:09,930 --> 00:15:12,720 And that sound instance is inside of the sound service. 235 00:15:12,930 --> 00:15:16,410 SFX Dot I believe it's called yeah breathing locker. 236 00:15:16,410 --> 00:15:18,480 We want to stop that sound. 237 00:15:19,050 --> 00:15:28,590 Then we can use our better tween service and we can go ahead and tween the self dot occupant dot humanoid 238 00:15:28,590 --> 00:15:32,940 route part, because we're going to be moving their route part in and out of our locker. 239 00:15:32,940 --> 00:15:37,350 As you can see we have a humanoid route part copy here that's on the outside of the locker. 240 00:15:37,350 --> 00:15:39,420 And we also have one on the inside of the locker. 241 00:15:39,420 --> 00:15:42,660 So when they want to go in, we tween their character to move in. 242 00:15:42,660 --> 00:15:46,680 And then when they want to exit, we tween their character and move them to this position here. 243 00:15:46,680 --> 00:15:49,080 So we're going to tween their humanoid route part. 244 00:15:49,500 --> 00:15:50,940 We could do a tween info. 245 00:15:50,940 --> 00:15:53,700 Dot knew of something like 0.6 seconds. 246 00:15:54,270 --> 00:16:02,460 And then we're going to set the keyframe of our players character equal to the self dot locker. 247 00:16:03,420 --> 00:16:04,320 Model. 248 00:16:04,320 --> 00:16:07,650 And then there's a part in there called root part outside. 249 00:16:07,650 --> 00:16:12,690 And then we're going to set their humanoid root part, see frame to that one, after which we can go 250 00:16:12,690 --> 00:16:15,570 ahead and yield 4.6 seconds. 251 00:16:16,230 --> 00:16:22,980 And then we're going to set an attribute on this player of inside locker equal to false. 252 00:16:23,430 --> 00:16:30,120 And then we can do the self dot occupant and refer to the humanoid root part again. 253 00:16:30,360 --> 00:16:34,710 And this is because when they're inside of the locker we're going to anchor their humanoid root part. 254 00:16:34,710 --> 00:16:39,690 So to give them control back over their character we're going to set the anchor property to false. 255 00:16:40,050 --> 00:16:43,470 And then we're going to go ahead and finally set occupant equal to nil. 256 00:16:43,770 --> 00:16:47,640 Now we can basically do the exact same thing when we want to set an occupant. 257 00:16:47,640 --> 00:16:53,070 Again we're going to set self dot occupant equal to the character passed to this function. 258 00:16:53,160 --> 00:16:54,960 And then we're also going to get the player. 259 00:16:54,960 --> 00:16:59,460 So players get player from character and pass the character model. 260 00:17:00,340 --> 00:17:06,430 And then we're going to set an attribute on that player of inside locker equal to true. 261 00:17:06,910 --> 00:17:11,260 And then we're going to go ahead and anchor their humanoid root part. 262 00:17:11,260 --> 00:17:13,840 So dot anchor ID is equal to true. 263 00:17:14,690 --> 00:17:21,320 And then we're going to use our better tween and tween the character dot humanoid root part. 264 00:17:22,700 --> 00:17:30,680 We'll do a tween info again of 0.6 seconds, and this time we want to set the C frame equal to the self 265 00:17:30,680 --> 00:17:32,270 dot locker model. 266 00:17:32,270 --> 00:17:35,240 And this part is called root part inside. 267 00:17:35,240 --> 00:17:37,100 And we'll set it to that C frame. 268 00:17:37,900 --> 00:17:42,250 Afterwards, we can go ahead and yield for the duration of this tween, and then we're going to use 269 00:17:42,250 --> 00:17:48,610 the game comms event and fire to this client to go ahead and play the breathing sound. 270 00:17:48,610 --> 00:17:57,070 So player game comms enum dot two client dot play sound and the sound is equal to the sound service 271 00:17:57,070 --> 00:18:04,840 dot sfx dot uh breathing locker and then play at point we're going to set to false. 272 00:18:04,840 --> 00:18:12,700 And then something that's very important for us to do is we need to turn the player's camera to face 273 00:18:12,700 --> 00:18:16,930 the correct way, because when they're running towards this locker and they want to go inside, their 274 00:18:16,930 --> 00:18:19,450 camera's going to be facing the other side of the locker. 275 00:18:19,450 --> 00:18:25,780 So what we want to do is we want to adjust the rotation of the player's camera to rotate all the way 276 00:18:25,780 --> 00:18:29,410 around and face the correct direction inside of the locker. 277 00:18:29,410 --> 00:18:36,100 So what we could do is we could use the camera manipulation event and fire to this particular player 278 00:18:36,100 --> 00:18:39,970 that we need them to get the enum dot two client. 279 00:18:39,970 --> 00:18:42,550 We want them to rotate their camera. 280 00:18:43,510 --> 00:18:46,420 The tween data we can pass to this. 281 00:18:46,420 --> 00:18:49,300 We could do a rotation time of like one second. 282 00:18:49,300 --> 00:18:54,460 And then for the rotation we're going to set that to zero degrees on the x axis. 283 00:18:54,460 --> 00:18:59,380 And then we're going to use math dot rad and refer to self dot locker model. 284 00:18:59,380 --> 00:19:06,250 Get the root part that is inside and get the orientation of it around the y axis. 285 00:19:07,230 --> 00:19:10,680 And then afterwards we're going to do zero on the z axis. 286 00:19:10,680 --> 00:19:15,780 And the last thing we want to pass is a condition rotate around head if you remember. 287 00:19:15,780 --> 00:19:17,940 And we want to set that equal to true. 288 00:19:17,940 --> 00:19:23,760 That way when the camera rotates it's equivalent or equal to the offset that the camera will be when 289 00:19:23,760 --> 00:19:24,990 they're in first person. 290 00:19:24,990 --> 00:19:29,760 So once we do that, we can go ahead and yield for the one second that they'll be rotating their camera 291 00:19:29,760 --> 00:19:30,480 around. 292 00:19:30,750 --> 00:19:34,020 And then once they do that, we can go ahead and tell them to reset their camera. 293 00:19:34,020 --> 00:19:37,590 So the default camera control scripts, you know, have control again. 294 00:19:37,590 --> 00:19:47,580 So camera manipulation event fire client player camera manipulation enum dot two client dot reset camera. 295 00:19:47,580 --> 00:19:53,910 And then finally we can set the self dot exit prompt dot enabled equal to true. 296 00:19:54,030 --> 00:19:58,260 Now something that's very important is that we're actually going to have to go into our camera manipulation 297 00:19:58,260 --> 00:20:03,750 handler, because there's actually a little bit of changes that I want to make for when we reset the 298 00:20:03,750 --> 00:20:04,200 camera. 299 00:20:04,200 --> 00:20:07,260 And when we rotate the camera around the players head. 300 00:20:07,260 --> 00:20:14,370 And so in fact, I actually found a better formula for making sure that the camera is as close as possible 301 00:20:14,370 --> 00:20:18,240 to the correct position when the camera is in first person mode. 302 00:20:18,480 --> 00:20:22,650 So what we're going to do here is we're going to delete this. 303 00:20:23,210 --> 00:20:28,160 And for the C frame that we want to set it to when we reset the camera, we're going to do C frame dot 304 00:20:28,160 --> 00:20:28,760 new. 305 00:20:28,790 --> 00:20:34,430 We're going to get the local player get their character and then get their head dot position right. 306 00:20:34,430 --> 00:20:40,850 And now we need to offset it appropriately to match as close as possible to where the camera is located 307 00:20:40,850 --> 00:20:43,190 relative to the head when they're in first person mode. 308 00:20:43,190 --> 00:20:50,450 And I found that equal to a vector three dot new for the x position, we need to offset it by the local 309 00:20:50,450 --> 00:20:52,340 player dot character. 310 00:20:52,340 --> 00:20:56,060 We're going to get their humanoid root part so we know what direction they're facing. 311 00:20:56,060 --> 00:20:59,090 We'll get the C frame of that and then get the look vector. 312 00:20:59,510 --> 00:21:02,720 And we're going to get the x component of that look vector. 313 00:21:02,720 --> 00:21:06,860 And then we actually need to subtract or negate this value. 314 00:21:06,860 --> 00:21:11,150 So that way we move the head position back in this x direction. 315 00:21:11,660 --> 00:21:16,700 Not only do we need to negate it, but we also need to multiply it by 0.5 or basically cut the value 316 00:21:16,700 --> 00:21:22,340 in half, because that's what I found to be relatively close to where the player's camera position is 317 00:21:22,340 --> 00:21:23,180 going to be at. 318 00:21:23,180 --> 00:21:30,380 For the Y, I found it to be constant of an offset of around 0.13 studs above the player's head, and 319 00:21:30,380 --> 00:21:38,270 then for the Z, we can do the exact same thing of local player dot character dot humanoid root part. 320 00:21:38,570 --> 00:21:41,960 Get the C frame, get the look vector. 321 00:21:41,960 --> 00:21:46,010 And this time we're going to get the z component of that look vector. 322 00:21:46,010 --> 00:21:50,360 And we do not need to negate it, but we still need to multiply it or cut it in half. 323 00:21:50,860 --> 00:21:58,120 And I found this C frame to be nearly almost identical to the position that the camera will be in when 324 00:21:58,120 --> 00:21:59,290 they're in first person mode. 325 00:21:59,290 --> 00:22:06,850 So we can copy this now, and also update that C frame to when we need to rotate our camera around the 326 00:22:06,850 --> 00:22:07,780 head of the player. 327 00:22:07,780 --> 00:22:10,120 So we'll go ahead and paste that right there. 328 00:22:11,930 --> 00:22:16,730 So we are completed scripting inside of our locker service, and we're also completed scripting in our 329 00:22:16,730 --> 00:22:18,230 camera manipulation handler. 330 00:22:18,230 --> 00:22:23,090 One last change I want to make is going to be inside of the sounds handler on the client. 331 00:22:23,090 --> 00:22:25,160 So go ahead and make sure you open that up. 332 00:22:25,490 --> 00:22:29,420 And what we're going to be adjusting here is our fade sound out function. 333 00:22:29,570 --> 00:22:36,890 Now what we want to do is we actually want to go ahead and get the original volume of the sound that 334 00:22:36,890 --> 00:22:40,220 we're about to fade out, so we can pass sound volume here. 335 00:22:40,220 --> 00:22:45,740 And that's because after we have faded this sound out and set the volume to zero, we never set the 336 00:22:45,740 --> 00:22:48,200 volume of the sound back to its original volume. 337 00:22:48,200 --> 00:22:52,310 This is a problem because if we want to play the sound again in the future, it's going to be completely 338 00:22:52,310 --> 00:22:52,970 muted. 339 00:22:53,150 --> 00:22:58,850 So we get the original volume, we play the scene to drown it out, and then once the sound is stopped, 340 00:22:58,850 --> 00:23:04,100 we can go ahead and set the sound's volume property back to the original value so we can do sound dot 341 00:23:04,100 --> 00:23:07,190 volume equal to original volume. 342 00:23:07,920 --> 00:23:08,670 Great. 343 00:23:08,670 --> 00:23:11,400 Now that we have done all that, we should be complete. 344 00:23:11,430 --> 00:23:16,590 So now we can go ahead and test out this locker that I've copied from the basement and see what it does. 345 00:23:16,800 --> 00:23:17,430 Okay. 346 00:23:17,430 --> 00:23:19,950 So let's go ahead and enter our locker here. 347 00:23:19,950 --> 00:23:22,410 As you can see we have our prompt that says locker enter. 348 00:23:22,410 --> 00:23:27,570 So if we hold down e unfortunately it looks like nothing is happening. 349 00:23:27,570 --> 00:23:32,730 So we got to figure out why exactly we are not able to enter our locker. 350 00:23:33,390 --> 00:23:38,700 Oh and silly me, actually forgot that we didn't completely set up this section in our if statement, 351 00:23:38,700 --> 00:23:39,870 so we're not done yet. 352 00:23:39,870 --> 00:23:46,380 So when a prompt gets triggered and there's no occupant and we want to set the player to be inside of 353 00:23:46,380 --> 00:23:49,530 this locker, first we need to put a return statement in here. 354 00:23:49,530 --> 00:23:51,240 If the player is already in a locker. 355 00:23:51,240 --> 00:23:58,020 And then afterwards we're going to spawn our open closed door function in a new thread and we'll pass 356 00:23:58,020 --> 00:23:58,560 self. 357 00:23:58,560 --> 00:24:01,830 And then we need to do self set occupant. 358 00:24:03,180 --> 00:24:06,870 And then we need to pass our player dot character. 359 00:24:06,870 --> 00:24:08,730 So we forgot to fill this section out here. 360 00:24:08,730 --> 00:24:13,140 But now that we have this set up, when we activate our prompt we should be good to go. 361 00:24:13,140 --> 00:24:17,490 So let me go ahead and review over the code just real quick to make sure I didn't miss anything else. 362 00:24:17,490 --> 00:24:22,020 Everything is looking good so far and I don't believe I see any more issues. 363 00:24:22,020 --> 00:24:25,170 So now our locker service should be working. 364 00:24:25,890 --> 00:24:27,390 Okay, moment of truth. 365 00:24:27,390 --> 00:24:28,230 Let's try it out again. 366 00:24:28,230 --> 00:24:30,270 If we hit E, there we go. 367 00:24:30,270 --> 00:24:33,750 We rotate the camera around and boom, we're inside of the locker. 368 00:24:33,750 --> 00:24:38,280 As you can see, our camera rotated around and then reset the position back. 369 00:24:38,280 --> 00:24:43,230 There was a little bit of a snap to move the camera back to its original position, but that's as close 370 00:24:43,230 --> 00:24:45,060 as I've gotten with the math. 371 00:24:45,150 --> 00:24:48,090 And if we hit E again, we should be able to exit the locker. 372 00:24:49,140 --> 00:24:49,590 Perfect. 373 00:24:49,590 --> 00:24:54,420 It moves us out, and then we should be able to enter back in just like that. 374 00:24:54,420 --> 00:25:00,600 And I don't know if you can hear it, but if you listen carefully, you should be able to hear the breathing 375 00:25:00,600 --> 00:25:02,040 sound that we've placed in there right now. 376 00:25:02,040 --> 00:25:06,420 It's muffled because we're not in the basement, but it appears that everything is working correctly 377 00:25:06,420 --> 00:25:08,010 with our locker system. 378 00:25:11,190 --> 00:25:16,620 So in the next lecture, we're going to go ahead and script the spawning system for the basement key. 379 00:25:16,680 --> 00:25:18,300 I'll go ahead and see you there.